/*
 * Copyright 2015 MingxingWang

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 *     http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.audaque.graphdb.example

import java.io.File
import java.lang._

import com.audaque.graphdb.data.{EdgeSource, VertexSource}
import com.audaque.graphdb.{Property, LGraph, LGraphDB, Type}
import org.apache.spark.graphx.{VertexId, Edge => XEdge}

import scala.collection.mutable.HashSet
import scala.util.Random

/**
 * Created by Ming on 2015/3/14.
 */
object Example {
  val random = new Random(System.currentTimeMillis())
  var vCount: Long = 1
  var eCount: Long = 1
  val graphdb: LGraphDB = new LGraphDB(new File("example/GraphDB"))
  val graphName = "Person"

  def createGraph() {
    if (!graphdb.createGraph(graphName)) {
      return
    }
    val vertexField = Array[(String, Type)](("name", Type.String),
      ("sex", Type.Int),
      ("age", Type.Int),
      ("phone", Type.String),
      ("email", Type.String))
    val vertex = new VertexSource("example/Person_vertices.csv", "person", vertexField)
    vertex.indexFields = Set[String]("name", "phone", "email")
    vertex.charset = "UTF8"
    val edgeField = Array[(String, Type)](("type", Type.String))
    val edge = new EdgeSource("example/Person_edges.csv", "relation", edgeField)
    edge.charset = "UTF8"
    graphdb.loadDataIntoGraph(graphName, Array(vertex, edge))
  }

  def main(args: Array[String]) {
    createGraph()
    val graph = graphdb.openGraph(graphName)
    print("Load data from file ")
    vCount = graph.vertexCount()
    eCount = graph.edgeCount()
    println("Vertex count:" + vCount)
    println("Edge count:" + eCount)
    println("\nSearchFamily: 38")
    searchFamily(38, graph)
    println("\nSearch: phone=13808151245")
    graph.searchVertexKV("phone", "13808151245").foreach(_.debug())
    println("\nSearch: phone=13808151245 and name=宗腧")
    graph.searchVertexKV2(Set("phone" -> "13808151245", "name" -> "宗腧"), true).foreach(_.debug())
    val companySchema = graph.genSchema("Company", Array("name" -> Type.String, "address" -> Type.String, "phone" -> Type.String, "KK" -> Type.Int))
    val audaqueProp = Property(companySchema, Array("华傲数据", "深圳市南山区科技园软件大厦713", "075586329661", 100))
    val audaqueVertex = graph.addVertex(audaqueProp)
    println("\nAdd a company to graph: " + audaqueVertex.vid)
    graph.findVertex(audaqueVertex.vid).get.debug()
    //modify a vertex
    audaqueVertex.prop.set("KK", 200)
    graph.findVertex(audaqueVertex.vid).get.debug()
    val relSchema = graph.getSchema("relation").get
    graph.addEdge(808, audaqueVertex.vid, Property(relSchema, Array("就职")))
    graph.findOutEdges(808).foreach(_.debug())
    graph.deleteVertexAndEdges(audaqueVertex.vid)
    println("After delete:")
    graph.findOutEdges(808).foreach(_.debug())
    graph.save()
  }

  def searchFamily(vid: VertexId,
                   graph: LGraph,
                   level: Int = 1,
                   vids: HashSet[VertexId] = HashSet[VertexId]()) {
    val person = graph.findVertex(vid) match {
      case Some(p) => p
      case None => return
    }
    if (level == 1) {
      vids += vid
      person.debug()
    }
    val oe = graph.findOutEdges(vid)
    oe.foreach(e => {
      val rel = e("type").asInstanceOf[String]
      if ("夫妻".equals(e("type").asInstanceOf[String]) && !vids.contains(e.dstId)) {
        graph.findVertex(e.dstId) match {
          case Some(p) =>
            vids += p.vid
            print("  |  " * (level - 1))
            print(rel + " ->")
            p.debug()
            searchFamily(p.vid, graph, level + 1, vids)
          case None =>
        }
      }
    })
    oe.foreach(e => {
      val rel = e("type").asInstanceOf[String]
      if (!"夫妻".equals(e("type").asInstanceOf[String]) && !vids.contains(e.dstId)) {
        graph.findVertex(e.dstId) match {
          case Some(p) =>
            vids += p.vid
            print("  |  " * level)
            print(rel + " ->")
            p.debug()
            searchFamily(p.vid, graph, level + 1, vids)
          case None =>
        }
      }
    })
  }

}
